//Learned:
//1.结构体相关字段初始化一次即可，不用放在循环里！
//2.接收和发送用的是两个不同的结构体变量！
//  有点像文件那，以读的权限打开后若想写，需要先关闭，再以写打开，即要保证“独立”
//3.改成多线程处理时，由于只有一个void*参数，但要同时用到sockfd和sockaddr_in结构体，故可以再用一个结构体封装而不用把sockfd设为全局的了
#include <iostream>
#include "log.hpp"
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
using std::string;

#define NUM 4096
int socketfd = 0;
// ./udpclient serverip serverport
void Usage(char *s)
{
    cout << "Usage of " << s << ": " << string(s) + " + serverip"
         << " + serverport" << endl;
}

void* recvMessage(void* arg)
{
    sockaddr_in* server = static_cast<sockaddr_in*>(arg);
    char buffer[NUM] = {0};
    while(true)
    {
        sockaddr_in server_echo;
        socklen_t len = sizeof(server_echo);
        memset(buffer,0,sizeof(buffer));
        int n = recvfrom(socketfd, buffer, sizeof(buffer), 0, (sockaddr*)&server_echo, &len);
        cerr << buffer << endl;         //往标准错误上输出，这样可以通过重定向将收发消息的界面分离！
    }
    return nullptr;
}

void* sendMessage(void* arg)
{
    sockaddr_in* server = static_cast<sockaddr_in*>(arg);
    while (true)
    {
        string s;
        cout << "client@: ";
        getline(cin, s);
        
        socklen_t len = sizeof(*server);
        sendto(socketfd, s.c_str(), s.size(), 0, (sockaddr*)server, len); 
        usleep(10000);
    }
    return nullptr;
}



int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        Usage(argv[0]);
    }
    else
    {
        // 1.获取socket
        socketfd = socket(AF_INET, SOCK_DGRAM, 0);

        // 2.结构体字段初始化
        sockaddr_in server;
        bzero(&server, sizeof(server));
        server.sin_family = AF_INET;

        int port = stoi(argv[2]);
        server.sin_port = htons(port);
        server.sin_addr.s_addr = inet_addr(argv[1]);
        
        pthread_t rid,sid;
        pthread_create(&rid,nullptr,recvMessage,&server);
        pthread_create(&sid,nullptr,sendMessage,&server);

        //3.客户端动作  -->  拆分成多线程实现简易聊天室   
        // while (true)
        // {
        //     string s;
        //     cout << "client@: ";
        //     getline(cin, s);
            
        //     sendto(socketfd, s.c_str(), s.size(), 0, (sockaddr*)&server, (socklen_t)sizeof(server)); 
        //     char buffer[NUM] = {0};

        //     sockaddr_in server_echo;
        //     socklen_t len = sizeof(server_echo);
        //     int n = recvfrom(socketfd, buffer, sizeof(buffer), 0, (sockaddr*)&server_echo, &len);

        //     buffer[n] = 0;
        //     cout << "echo: " << buffer << endl;
        // }

        pthread_join(rid,nullptr);
        pthread_join(sid,nullptr);
    }

    return 0;
}